home *** CD-ROM | disk | FTP | other *** search
- Program FlagTest; { Generates a comlete report of Intel CPU flag behavior }
- { Version 2.0· Last modified 27-03-94 }
-
- Uses CRT,DOS;
-
- CONST
- StartCount = -4;
- EndCount = 10;
-
- Normcol=$07; {normal}
- Flipcol=$70; {inverse}
- Setcol=$0C; {bright red}
- Clearcol=$02; {green}
- Stillcol=$09; {bright blue}
- Lowcol=$06; {brown}
-
- VAR
- Count:integer;
- Tmpflag:byte;
-
-
- { TestRoutine contains the actual instruction(s) to be analyzed. }
- { On entry, AX=BX=CX=DX=SI=DI == 0 }
-
- Procedure TestRoutine;Assembler;
- ASM
-
- CMC { This is just a weird combination }
- MOV CX,COUNT { to demonstrate all possible outcomes }
- SHL CL,CL { of the FlagTest analysis. }
-
- END;
-
-
-
-
-
- Procedure CallTest;Assembler;
- ASM
- PUSH SI
- PUSHF {flags and SI are preserved}
-
- PUSHF
- POP AX
-
- AND AX,BX { clear flags - AND mask in BX }
- OR AX,DX { set flags - OR mask in CX }
-
- PUSH AX
- XOR AX,AX
- XOR BX,BX
- XOR DX,DX
- XOR SI,SI
- XOR DI,DI
- POPF { install our preset flags }
- Call TestRoutine
-
- PUSHF
- POP AX { flags output to AX }
-
- POPF
- POP SI
- END;{CallTest}
-
-
-
-
- Function TestFlag(Fbit:byte):byte; { output = 0/1/2/3 }
- BEGIN
- ASM
-
- {
- For precise flag behavior measurement, we test the situation
- where all other inputs (registers and flags) are zero.
- the testroutine is then called twice, once with the flag set
- and once with it cleared, to be able to detect cases where
- it is flipped or unaffected by the instruction(s) in TestRoutine.
- }
-
- MOV TMPFLAG,0
-
- MOV SI,1
- MOV CL,Fbit
- SHL SI,CL { SI now has bit Fbit set }
-
-
- MOV BX,$E32A { the AND mask - must set all flags to 0 }
- { but not touch undefined or system flags }
- MOV DX,$0000 { the OR mask }
- { we enter the first test with all flags cleared }
-
- XOR CX,CX
- Call CallTest { output in AX }
- AND AX,SI { isolate flag we're looking for }
- JZ @ov1
- OR TMPFLAG,1 { note result in bit 0 of output }
- @ov1:
-
-
- MOV BX,$E32A { the AND mask }
- MOV DX,SI { DX is the OR mask }
- { we enter the the second test with bit(Fbit) SET }
-
- XOR CX,CX
- Call CallTest { output in AX }
- AND AX,SI { isolate flag we're looking for }
- JZ @ov2
- OR TMPFLAG,2 { note result in bit 1 of output }
- @ov2:
-
- END;{asm}
-
- TestFlag:=TMPflag;
-
- END; {TestFlag}
-
-
-
-
- Function TestCXZ:byte; { output = 0/1/2/3 }
- BEGIN
- ASM
-
- MOV TMPFLAG,0
-
- MOV BX,$E32A ; { the AND mask }
- MOV DX,$0000 ; { OR mask }
-
- MOV CX,1 { start with CX = 0 condition 'CLEARED' }
- Call CallTest;
- OR CX,CX { test for CX=0 condition }
- JNZ @ov1
- OR TMPFLAG,1 { note result in bit 0 of output }
- @ov1:
-
- MOV BX,$E32A
- MOV DX,$0000
-
- MOV CX,0 { start with CX = 0 condition 'SET' }
- Call CallTest;
- OR CX,CX { test for CX=0 condition }
- JNZ @ov2
- OR TMPFLAG,2 { note result in bit 1 of output }
- @ov2:
-
- END;{asm}
-
- TestCXZ:=TMPflag;
-
- END;
-
-
-
- Function Illdefined(Fbit:byte):boolean;
- begin
- Illdefined:= ( TestFlag(Fbit) in [1,2] ); { not simply SET or CLEARED }
- end;
-
-
-
- Procedure PrintFlagBit(Fbit:byte;Fname:string);
- { print Fname in colors given by flag changes }
- var
- ChaID:byte;
- Icat:string[8];
- begin
- Write(' ');
-
-
- Case Fbit of
- 32: chaid:= TestCXZ;
- 33: begin
- chaid:= ((TestFlag(0) or TestFlag(6)) xor 3); {JA}
- if Illdefined(0) or Illdefined(6) then Chaid:=4;
- end;
- 34: begin
- chaid:= ((TestFlag(7) xor TestFlag(11)) xor 3); {JGE}
- if Illdefined(7) or Illdefined(11) then Chaid:=4;
- end;
- 35: begin
- chaid:=(((TestFlag(7) xor TestFlag(11)) {JG}
- or TestFlag(6)) xor 3) ;
- if Illdefined(7) or Illdefined(11) or Illdefined(6) then Chaid:=4;
- end;
- else ChaID:=TestFlag(Fbit);
- end; {case}
-
-
- Case ChaID of
- 0:begin Textattr:=Clearcol; Icat:=' O '; end; { Cleared }
- 1:begin Textattr:= Flipcol; Icat:=' X '; end; { Flipped }
- 2:begin Textattr:=Stillcol; Icat:=' U '; end; { Unchanged }
- 3:begin Textattr:= Setcol; Icat:=' 1 '; end; { Set }
- 4:begin Textattr:= Lowcol; Icat:=' - '; end; { Undefined }
- end;{case}
-
- Write(Fname);
-
- Textattr:=NormCol;
- Write(Icat);
-
- end;
-
-
-
- Procedure PrintAllFlags;
- Begin
- Write('∫'); { * These are the 'jumpable' flags }
- PrintFlagBit(0 ,'Carry');
- PrintFlagBit(6 ,'Zero');
- PrintFlagBit(7 ,'Sign');
- PrintFlagBit(11,'OF'); { Overflow }
- PrintFlagBit(2 ,'P'); { Parity }
- Write('≥'); { * The 'jumpable' cases depending on multiple flags }
- PrintFlagBit(33,'JA'); { Above (unsigned) }
- PrintFlagBit(34,'JGE'); { Greater or Equal (signed) }
- PrintFlagBit(35,'JG'); { Greater (signed) }
- Write('≥');
- PrintFlagBit(32,'CXZ'); { * Simply the CX=ZERO condition }
- Write('≥');
- PrintFlagBit(4 ,'Aux'); { * Not really useful but shown anyway ..}
-
- { PrintFlagBit(10,'Dir'); } { Wanna see the Direction flag instead }
-
- end;
-
-
-
- Function Redirected:Boolean;
- { detect if user wants redirectable output }
- Assembler;
- ASM
- MOV AX,04400h { query device info }
- MOV BX,1 { for device STDOUT }
- INT 021h
- XOR AX,AX
- ADD DL,DL { bit 7 clear = STDOUT redirected as FILE OUTPUT}
- CMC
- ADC AX,AX { prepare boolean output AX=1=True }
- END;
-
-
-
- BEGIN { MAIN }
-
- If Redirected then begin
- WriteLn(' FlagTest 2.0 - writing output to file ');
- { In Borland/Turbo Pascal, using CRT is needed to create }
- { color in text output; however this bypasses DOS so the }
- { output is not redirectable. Here we reroute the output }
- { to the official DOS STDOUT device again. }
- ASSIGN(Output,''); { Put pascal output back on real STDOUT.. }
- REWRITE(Output); { Open for writing }
- end;
-
- WriteLn;
- WriteLn('FlagTest 2.0· (C) Copyright 1994 by Erik de Neve');
- WriteLn;
- WriteLn(' Tested: CMC / MOV CX,(Input) / SHL CL,CL');
- WriteLn;
-
- Textattr:=NormCol;
- Write('Input ∫ Flags: ');
-
- Textattr:=setcol;
- Write(' 1: set ');
-
- Textattr:=clearcol;
- Write(' O: cleared ');
-
- Textattr:=stillcol;
- Write(' U: unchanged ');
-
- Textattr:=flipcol;
- Write(' X: flipped ');
-
- Textattr:=lowcol;
- Write(' -: undefined ');
-
- Textattr:=NormCol;
-
- WriteLn;
- WriteLn('ƒƒƒƒƒƒ◊ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ¬ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ¬ƒƒƒƒƒƒƒ¬ƒƒƒƒƒƒƒ');
-
- For Count:= startcount to endcount do
- BEGIN
- Write(Count:6);
- PrintAllFlags;
- WriteLn;
- END;
-
- END.
-
-